#ifndef DWAR_H
#define DWAR_H

#include <Arduino.h>
#include <FreeRTOS.h>
#include "device/screen.h"
#include "shared_val.h"
#include "probe/probe.h"
#include "BilinearInterpolation.h"
#include "colormap.h"


#define PROB_SCALE 10
#define _SCALE PROB_SCALE
static int mlx90640To_buffer[768];       // 缓存区域，复制MLX90640读取的温度数据并用于绘制热力图
const int biox = 32;
const int bioy = 24;
const int lines = 3;  // 一次渲染多少行的像素
uint16_t  lineBuffer[biox * PROB_SCALE * lines]; // Toggle buffer for lines
uint16_t  dmaBuffer1[biox * PROB_SCALE * lines]; // Toggle buffer for lines
uint16_t  dmaBuffer2[biox * PROB_SCALE * lines]; // Toggle buffer for lines
uint16_t* dmaBufferPtr = dmaBuffer1;
bool dmaBufferSel = 0;

// 绘制十字
inline void draw_cross(int x, int y, int len){
   tft.drawLine(x - len/2, y, x + len/2, y, tft.color565(255, 255, 255));
   tft.drawLine(x, y-len/2, x, y+len/2,  tft.color565(255, 255, 255));

   tft.drawLine(x - len/4, y, x + len/4, y, tft.color565(0, 0, 0));
   tft.drawLine(x, y-len/4, x, y+len/4,  tft.color565(0, 0, 0));
}

// 点测温功能
inline void show_local_temp(int x, int y, int cursor_size){
   draw_cross(x, y, 8);
   float temp_xy = mlx90640To[(24 - y / PROB_SCALE) * 32 + (x / PROB_SCALE)];
   int shift_x, shift_y;
   if (x<140){shift_x=10;} else {shift_x=-60;}
   if (y<120){shift_y=10;} else {shift_y=-20;}
   tft.setTextSize(2);
   tft.setCursor(x+shift_x, y+shift_y);
   tft.printf("%.2f", temp_xy);
}  

// 点测温功能
inline void show_local_temp(int x, int y){
   show_local_temp(x, y, 2);
}  

// 判断应该在什么时候渲染光标（光标位置在当前渲染行数-40行的时候）
// 这么做是为了让光标别闪
// 判断应该在什么时候渲染光标（光标位置在当前渲染行数-40行的时候）
// 这么做是为了让光标别闪
inline void insert_temp_cursor(int y){
   static int trig_line;
   trig_line = test_point[1] + 40;
   if (trig_line>215){trig_line = 215;}
   if (y==trig_line){
      if (flag_show_cursor==true) {show_local_temp(test_point[0], test_point[1]);}
   }
}



void draw(){
   static int value;
   static int now_y = 0;
   // 图像的渲染流程
   if(use_upsample){
      tft.startWrite();
      for(int y=0; y<24 * _SCALE; y++){ 
         for(int x=0; x<32 * _SCALE; x++){
            value = bio_linear_interpolation(x, y, mlx90640To_buffer);
            lineBuffer[x + now_y*32 * _SCALE] = colormap[value];
         }
         now_y ++;
         if(now_y==lines){
            if (dmaBufferSel) dmaBufferPtr = dmaBuffer2;
            else dmaBufferPtr = dmaBuffer1;
            dmaBufferSel = !dmaBufferSel; // Toggle buffer selection
            tft.pushImageDMA(0, y-now_y, 32*_SCALE, lines, lineBuffer, dmaBufferPtr);
            now_y = 0;
         }
         insert_temp_cursor(y);
      }
      if(now_y!=0){
         if (dmaBufferSel) dmaBufferPtr = dmaBuffer2;
         else dmaBufferPtr = dmaBuffer1;
         dmaBufferSel = !dmaBufferSel; // Toggle buffer selection
         tft.pushImageDMA(0, 24*_SCALE-now_y-1, 32*_SCALE, now_y, lineBuffer, dmaBufferPtr);
         now_y = 0;
      }
      tft.endWrite(); 
   }else{
      static uint16_t c565;
      tft.setRotation(1);
      tft.startWrite();
      for (int i = 0; i < 24 ; i++){
      for (int j = 0; j < 32; j++){
         c565 = colormap[mlx90640To_buffer[(23-i)*32 + j]];
         tft.fillRect(j * _SCALE, (i * _SCALE), _SCALE, _SCALE, c565);  
      }
      }
      tft.setRotation(1);
      if (flag_show_cursor==true) {show_local_temp(test_point[0], test_point[1]);}
      tft.endWrite();
   }
   if (flag_trace_max==true) {draw_cross(max_y * _SCALE, (23-max_x) * _SCALE, 8);}
}

// 用来处理画面被暂停时的热成像图层的渲染工作
void freeze_handeler(){
   // 仅拍照模式下，位于第一屏时会启用这个功能
   if (flag_clear_cursor) {draw(); flag_clear_cursor=false;} // 通过重新渲染一张画面来清除光标
   if (flag_show_cursor) {
      show_local_temp(test_point[0], test_point[1]);
   } // 每次点击都渲染光标位置
}


// 探头准备期间的渲染管线
void preparing_loop(){
   tft.setRotation(1);
   if (prob_status == PROB_CONNECTING){
      tft.setCursor(40, 180);
      tft.setTextColor(TFT_WHITE, TFT_BLACK, true);
      tft.setTextSize(1);
      tft.fillRect(40, 180, 220, 30, TFT_BLACK); 
      tft.printf("Triying to connect to MLX...");
      tft.setCursor(80, 190);
      tft.printf("address: %d\n", 0x33);
      delay(10);
   }else if(prob_status == PROB_INITIALIZING){
      tft.setCursor(40, 180);
      tft.setTextColor(TFT_WHITE, TFT_BLACK, true);
      tft.setTextSize(1);
      tft.fillRect(40, 180, 200, 30, TFT_BLACK); 
      tft.printf("MLX... is ready, initializing...\n");
      delay(10);
   }else if(prob_status == PROB_PREPARING){
      tft.setCursor(40, 180);
      tft.setTextColor(TFT_WHITE, TFT_BLACK, true);
      tft.setTextSize(1);
      tft.fillRect(40, 180, 200, 30, TFT_BLACK); 
      tft.printf("MLX... initializing... \n"); 
      delay(10);
   }
}

// 准备期间的渲染管线
void refresh_status(uint8_t tp_status){
   if (tp_status == TP_CONNECTING){
      tft.setCursor(40, 180);
      tft.setTextColor(TFT_WHITE, TFT_BLACK, true);
      tft.setTextSize(1);
      tft.fillRect(40, 180, 220, 30, TFT_BLACK); 
      tft.printf("prepering touch panel...");
      delay(10); 
   }else if (tp_status == TP_READY){
      tft.setCursor(40, 180);
      tft.setTextColor(TFT_WHITE, TFT_BLACK, true);
      tft.setTextSize(1);
      tft.fillRect(40, 180, 220, 30, TFT_BLACK); 
      tft.printf("touch panel connected...");
      delay(10); 
   }else if (tp_status == TP_NOTFOUND){
      tft.setCursor(40, 180);
      tft.setTextColor(TFT_WHITE, TFT_BLACK, true);
      tft.setTextSize(1);
      tft.fillRect(40, 180, 220, 30, TFT_BLACK); 
      tft.printf("touch panel notfound...");
      delay(10); 
   }
}

// 处理tft_espi渲染管线
void screen_loop(){
   static unsigned long dt;
   if(!flag_in_photo_mode){
      dt = millis();
      while (prob_lock == true) {delay(5);}
      pix_cp_lock = true;
      for (int i = 0; i < 768; i++) {  // 拷贝温度信息, 并提前映射到色彩空间中
         mlx90640To_buffer[i] = (int)(180.0 * (mlx90640To[i] - T_min) / (T_max - T_min));
      }
      pix_cp_lock = false;
      draw();
      dt = millis() - dt;
      if (flag_show_cursor==true){
         tft.setTextSize(1);
         tft.setCursor(25, 220);
         tft.printf("max: %.2f  ", T_max);
         tft.setCursor(25, 230);
         tft.printf("min: %.2f  ", T_min);

         tft.setCursor(105, 220);
         tft.printf("avg: %.2f  ", T_avg);
         tft.setCursor(105, 230);
         tft.printf("bat: %d %% ", vbat_percent);

         tft.setCursor(180, 220);
         tft.printf("bright: %d  ", brightness);
         tft.setCursor(180, 230);
         tft.printf("time: %d ", dt);
         tft.printf("ms     ");
      }
      while (cmap_loading_lock == true) {delay(1);} 
   }else{
      freeze_handeler();
   }
}



#endif